/*
 * Copyright (c) 2021 Futurewei Technologies, Inc.
 *
 * clang2mpl is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PSL v2. You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the
 * Mulan PSL v2 for more details.
 */
// RUN: %clang2mpl --ascii --verify %s -- -Wno-unused-value --target=aarch64-linux-elf
// RUN: cat %m | %FileCheck %s
int gA[5];

void foo(int x, int *p) {
  short a1[5][4];

  // CHECK: LOC 2 [[# @LINE + 2 ]]{{$}}
  // CHECK-NEXT: iread i32 <* i32> 0 (array 0 a64 <* <[5] i32>> (addrof a64 $gA, constval i32 1))
  gA[1];
  // CHECK: LOC 2 [[# @LINE + 2 ]]{{$}}
  // CHECK-NEXT: iread i32 <* i32> 0 (array 0 a64 <* <[5] i32>> (addrof a64 $gA, dread i32 %x))
  gA[x];
  // CHECK: LOC 2 [[# @LINE + 4 ]]{{$}}
  // CHECK-NEXT: iassign <* i32> 0 (
  // CHECK-NEXT:   array 0 a64 <* <[5] i32>> (addrof a64 $gA, constval i32 2),
  // CHECK-NEXT:   dread i32 %x)
  gA[2] = x;
  // CHECK: LOC 2 [[# @LINE + 4 ]]{{$}}
  // CHECK-NEXT: iassign <* i32> 0 (
  // CHECK-NEXT:   array 0 a64 <* <[5] i32>> (addrof a64 $gA, dread i32 %x),
  // CHECK-NEXT:   constval i32 5)
  gA[x] = 5;

  // CHECK: LOC 2 [[# @LINE + 2 ]]{{$}}
  // CHECK-NEXT: iread i32 <* i16> 0 (array 0 a64 <* <[5][4] i16>> (addrof a64 %a1, constval i32 2, constval i32 3)))
  a1[2][3];
  // CHECK: LOC 2 [[# @LINE + 2 ]]{{$}}
  // CHECK-NEXT: iread i32 <* i16> 0 (array 0 a64 <* <[5][4] i16>> (addrof a64 %a1, dread i32 %x, dread i32 %x))
  a1[x][x];
  // CHECK: LOC 2 [[# @LINE + 4 ]]{{$}}
  // CHECK-NEXT: iassign <* i16> 0 (
  // CHECK-NEXT:   array 0 a64 <* <[5][4] i16>> (addrof a64 %a1, constval i32 4, constval i32 1),
  // CHECK-NEXT:   sext i32 16 (dread i32 %x))
  a1[4][1] = x;
  // CHECK: LOC 2 [[# @LINE + 4 ]]{{$}}
  // CHECK-NEXT: iassign <* i16> 0 (
  // CHECK-NEXT:   array 0 a64 <* <[5][4] i16>> (addrof a64 %a1, constval i32 0, constval i32 0),
  // CHECK-NEXT:   constval i32 0)
  a1[0][0] = 0;

  // CHECK: LOC 2 [[# @LINE + 2 ]]{{$}}
  // CHECK-NEXT: iread i32 <* i32> 0 (array 0 a64 <* <[1] i32>> (dread a64 %p, constval i32 4))
  p[4];
  // CHECK: LOC 2 [[# @LINE + 2 ]]{{$}}
  // CHECK-NEXT: iread i32 <* i32> 0 (array 0 a64 <* <[1] i32>> (dread a64 %p, dread i32 %x))
  p[x];
  // CHECK: LOC 2 [[# @LINE + 4 ]]{{$}}
  // CHECK-NEXT: iassign <* i32> 0 (
  // CHECK-NEXT:   array 0 a64 <* <[1] i32>> (dread a64 %p, constval i32 5),
  // CHECK-NEXT:   dread i32 %x)
  p[5] = x;
  // CHECK: LOC 2 [[# @LINE + 4 ]]{{$}}
  // CHECK-NEXT: iassign <* i32> 0 (
  // CHECK-NEXT:   array 0 a64 <* <[1] i32>> (dread a64 %p, dread i32 %x),
  // CHECK-NEXT:   constval i32 6)
  p[x] = 6;
}

void bar(int argc, char *argv[]) {
  // CHECK: LOC 2 [[# @LINE + 4 ]]{{$}}
  // CHECK-NEXT: iread u32 <* u8> 0 (array 0 a64 <* <[1] u8>> (
  // CHECK-NEXT:   iread a64 <* <* u8>> 0 (array 0 a64 <* <[1] <* u8>>> (dread a64 %argv, constval i32 1)),
  // CHECK-NEXT:   constval i32 0))
  argv[1][0];
}
